/*
#
#  Copyright 2011 Matthew Jannace
#
#  This file is part of RoboCode BlackHoleAgent
#
#  RoboCode BlackHoleAgent is free software: you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation, either version 3 of the
#  License, or (at your option) any later version.
#
#  RoboCode BlackHoleAgent is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with RoboCode BlackHoleAgent. If not, see
#  <http://www.gnu.org/licenses/>.
#
 */
package com.jannaceltd.TeamBlackHoleBeer.Modules.HelperClasses;

import com.jannaceltd.TeamBlackHoleBeer.BlackHole_Abstract;
import com.jannaceltd.TeamBlackHoleBeer.Utilities.MathUtils;
import java.awt.geom.Point2D;
import java.io.Serializable;
import robocode.util.Utils;

/**
 * Class to store Generic Robot Information
 * @author Matthew Jannace <mjannace@gmail.com>
 * @version 1.0
 */
public class Robots implements Serializable {

    private static final long serialVersionUID = 5890963822395906392L;
    /**
     * Robots Name
     */
    protected String name;
    /**
     * Robots Energy Level
     */
    protected double energy;
    /**
     * Robots Alive or Dead State
     */
    protected boolean alive;
    /**
     * Robots XY position
     */
    protected Point2D.Double pos = new Point2D.Double();
    /**
     * Robots bearing
     */
    protected double bearing;
    /**
     * Robots heading
     */
    protected double heading;
    /**
     * Robots velocity
     */
    protected double velocity;
    /**
     * Robots distance
     */
    protected double distance;
    /**
     * Robots Change in heading
     */
    protected double changehead;
    /**
     * Time the Robots Object was last updated
     */
    protected long ctime;

    /**
     * Creates a Generic Robot Object
     */
    public Robots() {
        this.name = "";
        this.energy = 0.0;
        this.alive = true;
        this.pos = new Point2D.Double();
        this.bearing = 0.0;
        this.heading = 0.0;
        this.velocity = 0.0;
        this.distance = 0.0;
        this.changehead = 0.0;
        this.ctime = 0L;
    }

    /**
     * Creates a Generic Robot Object
     * @param Agent
     */
    public Robots(BlackHole_Abstract Agent) {
        this.name = "";
        this.energy = 0.0;
        this.alive = true;
        this.pos = new Point2D.Double((Agent.getBattleFieldWidth() / 2), (Agent.getBattleFieldHeight() / 2));
        this.bearing = 0.0;
        this.heading = 0.0;
        this.velocity = 0.0;
        this.distance = 0.0;
        this.changehead = 0.0;
        this.ctime = 0L;
    }

    /**
     * Creates a Generic Robot Object
     * @param name
     * @param energy
     * @param alive
     * @param pos
     * @param bearing
     * @param heading
     * @param velocity
     * @param distance
     * @param changehead
     * @param ctime
     */
    public Robots(
            String name,
            double energy,
            boolean alive,
            Point2D.Double pos,
            double bearing,
            double heading,
            double velocity,
            double distance,
            double changehead,
            long ctime) {
        this.name = name;
        this.energy = energy;
        this.alive = alive;
        this.pos = new Point2D.Double(pos.getX(), pos.getY());
        this.bearing = bearing;
        this.heading = heading;
        this.velocity = velocity;
        this.distance = distance;
        this.changehead = changehead;
        this.ctime = ctime;
    }

    /**
     * Return a Point2D location of a Robot at the Time specified in the Parameter
     * @param when
     * @return XY Location of Robot at When
     */
    public Point2D.Double guessPosition(long when) {
        double diff = when - ctime;
        double newY = pos.getX() + Math.cos(heading) * velocity * diff;
        double newX = pos.getY() + Math.sin(heading) * velocity * diff;

        return new Point2D.Double(newX, newY);
    }

    /**
     * Gets the Name of the Robot
     * @return name
     */
    public String getName() {
        return this.name;
    }

    /**
     * Sets the Name of the Robot
     * @param value
     */
    public void setName(String value) {
        this.name = value;
    }

    /**
     * Gets the Robots Energy Level
     * @return energy
     */
    public double getEnergy() {
        return this.energy;
    }

    /**
     * Sets the Robots Energy Level
     * @param value
     */
    public void setEnergy(double value) {
        this.energy = value;
    }

    /**
     * Gets the Alive Status of the Robot
     * @return alive
     */
    public boolean getAlive() {
        return this.alive;
    }

    /**
     * Sets the Alive status of the Robot
     * @param value
     */
    public void setAlive(boolean value) {
        this.alive = value;
    }

    /**
     * Gets the current Bearing to Robot in Radians
     * @return bearing
     */
    public double getBearingRadians() {
        return this.bearing;
    }

    /**
     * Calculates Bearing to Robot in Radians given the Agents Current position
     * and heading
     * @param Agent
     * @return bearing
     */
    public double getBearingRadians(BlackHole_Abstract Agent) {

        double CalcAngl = MathUtils.calcAngle(getPos(), Agent.getPos());
        double b = Utils.normalRelativeAngle(CalcAngl - Agent.getHeadingRadians());
        return b;
    }

    /**
     * Sets the current Bearing to Robot in Radians
     * @param value 
     */
    public void setBearingRadians(double value) {
        this.bearing = value;
    }

    /**
     * Gets the current heading of the Robot in Radians
     * @return heading
     */
    public double getHeadingRadians() {
        return this.heading;
    }

    /**
     * Sets the current heading of the Robot in Radians
     * @param value 
     */
    public void setHeadingRadians(double value) {
        this.heading = value;
    }

    /**
     * Gets the current Velocity of the Robot
     * @return velocity
     */
    public double getVelocity() {
        return this.velocity;
    }

    /**
     * Sets the current Velocity of the Robot
     * @param value 
     */
    public void setVelocity(double value) {
        this.velocity = value;
    }

    /**
     * Gets the X location of the Robot
     * @return pos.x
     */
    public double getX() {
        return this.pos.getX();
    }

    /**
     * Sets the X location of the Robot
     * @param value
     */
    public void setX(double value) {
        this.pos.setLocation(value, pos.getY());
    }

    /**
     * Gets the Y location of the Robot
     * @return pos.y
     */
    public double getY() {
        return this.pos.getY();
    }

    /**
     * Sets the Y location of the Robot
     * @param value
     */
    public void setY(double value) {
        this.pos.setLocation(pos.getX(), value);
    }

    /**
     * Gets the Point2D location of the Robot
     * @return pos
     */
    public Point2D.Double getPos() {
        return this.pos;
    }

    /**
     * Sets the Point2D location of the Robot
     * @param value
     */
    public void setPos(Point2D.Double value) {
        this.pos.setLocation(value);
    }

    /**
     * Gets the Distance from the Agent to the Robot
     * @return distance
     */
    public double getDistance() {
        return this.distance;
    }

    /**
     * Sets the Distance from the Agent to the Robot
     * @param value
     */
    public void setDistance(double value) {
        this.distance = value;
    }

    /**
     * Gets the Change in Heading
     * @return changehead
     */
    public double getChangehead() {
        return this.changehead;
    }

    /**
     * Sets the Change in Heading
     * @param value 
     */
    public void setChangehead(double value) {
        this.changehead = value;
    }

    /**
     * Gets the time of the Robot
     * @return time
     */
    public Long getCtime() {
        return this.ctime;
    }

    /**
     * Sets the time of the Robot
     * @param value 
     */
    public void setCtime(Long value) {
        this.ctime = value;
    }
}
